<?php

namespace Rexzy\Base;

class Core {
    public $config;
    public $ruleConfig;
    public $module;
    public $controller;
    public $actionName;
    private $_actionArg = array();
    
    public function __construct() {}
    
    public function init() {
        if ( !defined( 'APP_PATH' ) ) {
            throw new \Eexception( 'APP_PATH 不存在！' );
        }
        
        if ( !defined( 'APP_NAME' ) ) {
            throw new \Eexception( 'APP_NAME 不存在！' );
        }
        $this->initConfig();
        $this->_autoLoad();
        $this->errorHandle();
        $this->_parseRules();
        $this->runApp();
    }
    
    /**
     * 基础配置参数函数
     */
    public function initConfig() {
        $this->config = include( REXZY_ROOT . '/Data/config.php' );
        $this->ruleConfig = include APP_PATH . '/Conf/rules.php';
        
        //判断应用是否有公用配置，若存在引入
        $appConfigfile = APP_PATH . '/Conf/config.php';
        if ( file_exists( $appConfigfile ) ) {
            $appConfig = include $appConfigfile;
            if ( is_array( $appConfig ) ) {
                $this->config = array_merge( $this->config, $appConfig  );
            }
        } 
        
        //设置时区
        date_default_timezone_set( $this->config['timezone'] );  
        //设置字符编码
        header( 'charset=' . $this->config['encode'] );  
    }
    
    /**
     *  分割 rule 得到 模块、控制器 和 动作的函数
     */
    private function _parseRules() {
        $rules = new \Rexzy\Http\Rules( $this->ruleConfig ); 
        if ( isset( $rules->rule ) ) {
            $rule = $rules->distribute();
            if ( $rule != '' ) {
                $pageMessage = explode( '/', $rule );
                if ( count( $pageMessage > 0 ) ) {
                    $this->module = $pageMessage[0];
                    $this->controller = isset( $pageMessage[1] ) ? $pageMessage[1] : '';
                    $this->actionName = isset( $pageMessage[2] ) ? $pageMessage[2] : '';
                    $this->_actionArg = array_splice( $pageMessage, 3 );
                }
            }
        }
    }
    
    private function _autoLoad() {
        /**
        * 框架自动加载函数
        * 
        * @param string $className 声明类名
        */
        spl_autoload_register( function( $className ) {
            $realClassName = preg_replace('/\\\/', '/', $className);
            $loadFile = REXZY_ROOT . '/../' . $realClassName . '.php';
            if (file_exists( $loadFile ) ) {
                include $loadFile;
            }
        } );
        
        // 应用里面类的自动加载函数
        spl_autoload_register( function( $className ) {
            $realClassName = preg_replace('/\\\/', '/', $className);
            $loadFile = APP_PATH . '/../' . $realClassName . '.php';
            if (file_exists( $loadFile ) ) {
                include $loadFile;
            }
        } );
    }
    
    /**
     * 异常和错误处理函数
     */
    public function errorHandle() {
        /**
        * 错误处理函数
        * 
        * @param int $type 错误类型编码，通过$map数组查找对应错误类型名称
        * @param string $message 错误信息
        * @param string $path 错误文件路径
        * @param int $line 出现错误行数
        */
       set_error_handler( function( $type, $message, $path, $line ) {
           $map = array(
                   E_COMPILE_ERROR => 'Compile error',
                   E_COMPILE_WARNING => 'Compile warning',
                   E_CORE_ERROR => 'Core error',
                   E_CORE_WARNING => 'Core warning',
                   E_DEPRECATED => 'Deprecated',
                   E_ERROR => 'Error',
                   E_WARNING => 'Warning',
                   E_NOTICE => 'Notice',
                   E_PARSE => 'Parsing error',
                   E_RECOVERABLE_ERROR => 'Recoverable error',
                   E_STRICT => 'Strict',
                   E_USER_DEPRECATED => 'User deprecated',
                   E_USER_ERROR => 'User error',
                   E_USER_WARNING => 'User warning',
                   E_USER_NOTICE => 'User notice',
               );
            $errorType = $map[$type];
            $errorContent = date( 'Y-m-d H:i:s' ) . ' ' . $errorType . ' ' . $message . 
                    ' ' . $path . "($line)\n";
            $log = new Log();
            $log->write( $errorContent, DEBUG );
        } );

        /**
         * 异常处理函数
         * 
         * @param object $exception 异常对象
         */
        set_exception_handler( function( $exception ) {
            $trace = array();
            foreach ( $exception->getTrace() as $key => $value ) {
                if ( isset( $value['file'] ) ) {
                    $message = $value['file'] . ' ' . "(" . $value['line'] . ")";
                } else {
                    $message = 'Unknow';
                }
                $trace[] = $message;
            }
            $errorContent = date( 'Y-m-d H:i:s' ) . ' Exception ' . $exception->getMessage() . 
                    ' ' . $exception->getFile() . "(" . $exception->getLine() . ")" . 
                    "\nTrace:\n" . implode( "\n", $trace ) . "\n";
            $log = new Log();
            $log->write( $errorContent, DEBUG );
        } );
    }
    
    public function runApp() {
        // 判断进入的模块
        if ( isset( $this->module ) ) {
            $moduleName = $this->module;
        } else {
            $moduleName = $this->config['default_module'];
            $this->module = $this->config['default_module'];
        }
        
         //判断模块中是否存在配置文件，存在侧合并框架配置项，并覆盖框架中的相同项
        $moduleConfigFile = APP_PATH . '/Module/' . $moduleName . '/Conf/config.php';
        if ( file_exists( $moduleConfigFile ) ) {
            $moduleConfig = include $moduleConfigFile;
            if ( is_array( $moduleConfig ) ) {
                $this->config = array_merge( $this->config, $moduleConfig  ); 
            }
        } 
        
        // 判断进入的控制器
        if ( isset( $this->controller ) ) {
            $controllerName = $this->controller;
        } else {
            $controllerName = $this->config['default_controller'];
            $this->controller = $this->config['default_controller'];
        }

        // 判断进入的动作
        if ( isset( $this->actionName ) ) {
            $actionName = $this->actionName;
        } else {
            $actionName = $this->config['default_action'];
            $this->actionName = $this->config['default_action'];
        }
        
        //判断模块是否存在
        $moduleDir = APP_PATH . '/Module/' . $moduleName;
        if ( ! is_dir( $moduleDir ) ) {
            throw new \Exception( "Module: '$moduleName' not find!" );
        }
        
        // 判断控制器文件是否存在
        $controllerFile = APP_PATH . '/Module/' . $moduleName . '/Controller/' . $controllerName . '.php';
        if ( !file_exists( $controllerFile ) ) {
            throw new \Exception( "Controller file: '$controllerFile' not find!" );
        }

        //引入控制器文件
        require_once $controllerFile;  

        // 判断控制器类是否存在
        $controllerClass = APP_NAME . '\\Module\\' . $moduleName . '\\Controller\\' . $controllerName;
        if ( !class_exists( $controllerClass ) ) {
            throw new \Exception( "Controller class: '$controllerClass' not find!" );
        }

        // 实例控制器对象
        // 判断动作方法是否存在
        $controller = new $controllerClass();
        if ( !method_exists( $controller, $actionName ) ) {
            throw new \Exception( "Controller action: '$actionName' not find!" );
        }
        
        $controller->view->setDir( APP_PATH . '/Module/' . $moduleName . '/View/');
        $controller->view->setTemplate( "$controllerName/$actionName" );
        
        //触发动作
        call_user_func_array( array( $controller, $actionName ), $this->_actionArg );
    }
    
    
}
